/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       clouds.h
 * Author:     karooolek
 * Created on: Jan 5, 2010
 *
 **********************************************************************************************************************/

#ifndef CLOUDS_H_
#define CLOUDS_H_

#include "../graphics.h"

namespace mGameEngine
{
namespace Game
{

/**
 * Single clouds layer.
 * Clouds layer is specified with texture.
 * Texture is repeated between horizons,
 * scaling is relative to layers height and size.
 * Clouds can move if it's velocity is specified.
 * Lighting is based on sun position and color.
 */
class Clouds : public Graphics::Drawable
{
protected:
    /**
     * Timer used for simulation.
     */
    Timer _timer;

    /**
     * Texture.
     */
    const Graphics::Texture *_texture;

    /**
     * Density.
     */
    float _density;

    /**
     * Height of clouds base.
     */
    float _height;

    /**
     * Layer size.
     */
    float _size;

    /**
     * Velocity.
     */
    Vector2 _velocity;

    /**
     * Sun color.
     */
    Color _sunColor;

    /**
     * Sun direction.
     */
    Vector3 _sunDirection;

    /**
     * Penetration depth.
     */
    float _penetration;

public:
    /**
     * Create clouds.
     */
    Clouds();

//    Clouds(const Graphics::Texture *texture,
//            float height, float size, const Vector2 &velocity,
//            float density, float penetration,
//            const Color &sunColor = Color(1.0f, 1.0f, 1.0f, 1.0f),
//            const Vector3 &sunPosition = Vector3(1.0f, 0.0f, 0.0f));

    /**
     * Destroy clouds.
     */
    virtual ~Clouds();

    /**
     * Get clouds texture.
     * @return clouds texture.
     */
    const Graphics::Texture *getTexture() const
    {
        return _texture;
    }

    /**
     * Set clouds texture.
     * @param texture clouds texture.
     */
    void setTexture(const Graphics::Texture *texture)
    {
        _texture = texture;
    }

    /**
     * Get height of clouds base.
     * @return height of clouds base.
     */
    float getHeight() const
    {
        return _height;
    }

    /**
     * Set height of clouds base.
     * @param height height of clouds base.
     */
    void setHeight(float height)
    {
        if(height <= 0.0f)
        {
            return;
        }

        _height = height;
    }

    /**
     * Get clouds layer size.
     * @return clouds layer size.
     */
    float getSize() const
    {
        return _size;
    }

    /**
     * Set clouds layer size.
     * @param size clouds layer size.
     */
    void setSize(float size)
    {
        if(size <= 0.0f)
        {
            return;
        }

        _size = size;
    }

    /**
     * Get clouds layer velocity.
     * @return clouds layer velocity.
     */
    const Vector2 &getVelocity() const
    {
        return _velocity;
    }

    /**
     * Set clouds layer velocity.
     * @param velocity clouds layer velocity.
     */
    void setVelocity(const Vector2 &velocity)
    {
        _velocity = velocity;
    }

    /**
     * Get sun color.
     * @return sun color.
     */
    const Color &getSunColor() const
    {
        return _sunColor;
    }

    /**
     * Set sun color.
     * @param sunColor sun color.
     */
    void setSunColor(const Color &sunColor)
    {
        _sunColor = sunColor;
    }

    /**
     * Get sun direction.
     * @return sun direction.
     */
    const Vector3 &getSunDirection() const
    {
        return _sunDirection;
    }

    /**
     * Set sun direction.
     * @param sunDirection sun direction.
     */
    void setSunDirection(const Vector3 &dir)
    {
        _sunDirection = dir;
        _sunDirection.normalize();
    }

    /**
     * Get sun penetration depth.
     * @return sun penetration depth.
     */
    float getPenetrationDepth() const
    {
        return _penetration;
    }

    /**
     * Set sun penetration depth.
     * @param penetration sun penetration depth.
     */
    void setPenetrationDepth(float penetration)
    {
        if(penetration < 0.0f)
        {
            return;
        }

        _penetration = penetration;
    }

    /**
     * Get clouds layer density.
     * @return clouds layer density.
     */
    float getDensity() const
    {
        return _density;
    }

    /**
     * Set clouds layer density.
     * @param density clouds layer density.
     */
    void setDensity(float density)
    {
        if(density < 0.0f)
        {
            return;
        }

        _density = density;
    }

    /**
     * Draw clouds.
     */
    virtual void draw() const;
};

}
}

#endif // CLOUDS_H_
